package com.wh1200.mybatis.dao.tests

import com.wh1200.mybatis.dao.BaseTest
import com.wh1200.xmlless.test.dao.DepartmentDAO
import com.wh1200.xmlless.test.dao.RoleDAO
import com.wh1200.xmlless.test.dao.StudentDAO
import com.wh1200.xmlless.test.dao.UserDAO
import com.wh1200.xmlless.test.model.Department
import com.wh1200.xmlless.test.model.Role
import com.wh1200.xmlless.test.model.Student
import com.wh1200.xmlless.test.model.User
import jakarta.annotation.Resource
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull


/**
 *
 * Created by 吴昊 on 2018/12/14.
 *
 * @author 吴昊
 * @since 0.0.7
 */
class UserDAOTest : BaseTest() {

  @Resource
  private lateinit var dao: UserDAO

  @Resource
  private lateinit var departmentDAO: DepartmentDAO

  @Resource
  private lateinit var studentDAO: StudentDAO

  @Resource
  private lateinit var roleDAO: RoleDAO

  companion object {
    private val log: Logger = LoggerFactory.getLogger(UserDAOTest::class.java)
  }

  @Test
  @DisplayName("测试从数组中移除元素")
  fun removeElementFromArray() {
    val user = User(id = 2, name = "w").apply {
      roles = listOf(1, 2, 3)
    }
    dao.save(user)
    dao.updateRolesRemoveRoleById(2, 2)
    val user2 = dao.findById(2)
    assertNotNull(user2)
    assertEquals(listOf(1, 3), user2.roles)
  }


  @Test
  fun findByAnyRole() {
    dao.saveAll(
      listOf(
        User(id = 1, name = "a").apply {
          roles = listOf(1, 2, 3)
        },
        User(id = 2, name = "a").apply {
          roles = listOf(4, 5, 6)
        },
        User(id = 3, name = "a").apply {
          roles = listOf(7, 8, 9)
        }
      )
    )
    val res = dao.findByAnyRole(listOf(1, 4))
    assertEquals(2, res.size)
  }


  @Test
  @DisplayName("测试向数组中添加元素")
  fun addElementFromArray() {
    val user = User(id = 2, name = "w").apply {
      roles = listOf(1)
    }
    dao.save(user)
    dao.updateRolesAddRoleById(2, 2)
    val user2 = dao.findById(2)
    assertNotNull(user2)
    assertEquals(listOf(1, 2), user2.roles)
  }

  @Test
  @DisplayName("测试清空数组")
  fun clearArray() {
    val user = User(id = 2, name = "w").apply {
      roles = listOf(1, 2)
    }
    dao.save(user)
    dao.updateRolesSetEmptyById(2)
    val user2 = dao.findById(2)
    assertNotNull(user2)
    assert(user2.roles.isEmpty())
  }

  @Test
  @DisplayName("测试设置为null")
  fun setNull() {
    val department = Department(2, "部门2")
    departmentDAO.save(department)
    val user = User(id = 2, name = "w").apply {
      roles = listOf(1, 2)
      departmentId = 2
    }
    dao.save(user)
    val userInDb = dao.findById(user.id!!)
    assertNotNull(userInDb)
    assertNotNull(userInDb.departmentId)
    assertNotNull(userInDb.department)
    assertNotNull(userInDb.departmentName)
    dao.updateDepartmentIdSetNullById(2)
    val user2 = dao.findById(2)
    assertNotNull(user2)
    assert(user2.departmentId == null)
  }

  @Test
  @DisplayName("根据ID 批量删除")
  fun deleteBatchIds() {
    val user1 = User(name = "user1")
    val user2 = User(name = "user2")
    dao.save(user1)
    dao.save(user2)
    val id1 = user1.id
    val id2 = user2.id
    assertNotNull(id1)
    assertNotNull(id2)
    dao.deleteByIdIn(listOf(id1, id2))
  }

  @Test
  @DisplayName("根据ID 删除")
  fun deleteById() {
    val user = User(name = "abc")
    dao.save(user)
    val id = user.id
    assertNotNull(id)
    assertNotNull(dao.findById(id))
    dao.deleteById(id)
    assertNull(dao.findById(id))
  }

  @Test
  @DisplayName("查找关联对象字段")
  fun selectRoleListById() {
    val role = Role(name = "我是管理员")
    roleDAO.save(role)
    val user = User(name = "w", deleted = false)
    user.roles = listOf(role.id!!)
    dao.save(user)
    val id = user.id
    assertNotNull(id)
    val u2 = dao.findRoleListById(id)
    assertNotNull(u2)
    assert(u2.roleList.isNotEmpty())
  }

  @Test
  fun findAll2() {
    val studentId = "2"
    val student = Student(name = "张三").apply {
      id = studentId
    }
    studentDAO.save(student)
    val user = User(name = "a", id = 5).apply {
      this.studentId = studentId
    }
    dao.save(user)
    val name = dao.findStudentNameById(user.id!!)
    assertEquals(student.name, name)

  }

  @Test
  fun findAllNames() {
    val names = dao.findAllNames()
    log.info(names.toString())
    assert(names.size == dao.count())
  }

  @Test
  @DisplayName("测试排序")
  fun findAll() {
    dao.save(User(name = "w"))
    dao.save(User(name = "wt"))
    dao.save(User(name = "wtf"))
    val page = dao.findAll(
      PageRequest.of(
        0, 20, Sort.Direction.DESC, "id"
      )
    )
    assert(page.totalElements >= 3)
    assert(page.content.isNotEmpty())
    val index1 = page.content.indexOfFirst { it.name == "wtf" }
    val index2 = page.content.indexOfFirst { it.name == "wt" }
    val index3 = page.content.indexOfFirst { it.name == "w" }
    assert(index1 < index2)
    assert(index2 < index3)
  }

  @Test
  @DisplayName("测试关联查询")
  fun pageable() {
    val role = Role(name = "我是管理员")
    roleDAO.save(role)
    val user = User(name = "w", deleted = false)
    user.roles = listOf(role.id!!)
    dao.save(user)
    val id = user.id
    assertNotNull(id)
    val user2 = dao.findById(id)
    assertNotNull(user2)
    assertNotNull(user2.roles)
    assert(user2.roles.isNotEmpty())
    assert(user2.roleList.isNotEmpty())
  }

  @Test
  fun save() {
    val user = User(
      name = "w",
      deleted = false
    )
    dao.save(user)
    val id = user.id
    assertNotNull(id)
    assertNotNull(dao.findSimpleUserById(id))
    dao.deleteById(id)
  }

  @Test
  fun findById() {
    val user = User(
      id = 99988,
      name = "b"
    )
    dao.save(user)
    assertEquals(99988, user.id)
    val user2 = User(name = "c")
    dao.save(user2)
    val user2Id = user2.id
    assertNotNull(user2Id)
  }

  @Test
  fun saveAll() {
    val user1 = User(
      name = "test",
      deleted = false
    )
    val user2 = User(
      name = "w",
      deleted = false
    )
    dao.saveAll(listOf(user1, user2))
    val user1Id = user1.id
    val user2Id = user2.id
    assertNotNull(user1Id)
    assertNotNull(user2Id)
    dao.deleteById(user1Id)
    dao.deleteById(user2Id)
  }

  @Test
  fun saveBatch() {
    val user1 = User(
      name = "test",
      deleted = false
    )
    val user2 = User(
      name = "w",
      deleted = false
    )
    dao.saveBatch(listOf(user1, user2))
    val user1Id = user1.id
    val user2Id = user2.id
    assertNotNull(user1Id)
    assertNotNull(user2Id)
    dao.deleteById(user1Id)
    dao.deleteById(user2Id)
  }

}
